package com.fastjrun.ciagent;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.fastjrun.ciagent.helper.IOHelper;
import com.fastjrun.ciagent.helper.ZipFileHelper;
import com.fastjrun.cidev.client.CidevClient;
import com.fastjrun.cidev.packet.req.GetModuleRequestBody;
import com.fastjrun.cidev.packet.req.GetUploadTokenRequestBody;
import com.fastjrun.cidev.packet.res.GetModuleResponseBody;
import com.fastjrun.cidev.packet.res.GetUploadTokenResponseBody;
import com.fastjrun.helper.EncryptHelper;

public class ModuleGenerator {
    protected final Log log = LogFactory.getLog(this.getClass());

    protected String accessKey;

    protected String accessKeySn;

    protected String apiUrlPre;
    
    private String appName;

    protected String packagePrefix;

    protected String tmpWorkSpace;

    protected String projectDir;

    protected String codeDir;

    protected String srcFile;

    protected String moduleName;

    public String getCodeDir() {
        return codeDir;
    }

    public void setCodeDir(String codeDir) {
        this.codeDir = codeDir;
    }

    public String getAccessKey() {
        return accessKey;
    }

    public void setAccessKey(String accessKey) {
        this.accessKey = accessKey;
    }

    public String getAccessKeySn() {
        return accessKeySn;
    }

    public void setAccessKeySn(String accessKeySn) {
        this.accessKeySn = accessKeySn;
    }

    public String getApiUrlPre() {
        return apiUrlPre;
    }

    public void setApiUrlPre(String apiUrlPre) {
        this.apiUrlPre = apiUrlPre;
    }

    public String getAppName() {
        return appName;
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }

    CidevClient cidevClient;

    public String getModuleName() {
        return moduleName;
    }

    public void setModuleName(String moduleName) {
        this.moduleName = moduleName;
    }

    public String getSrcFile() {
        return srcFile;
    }

    public void setSrcFile(String srcFile) {
        this.srcFile = srcFile;
    }

    public String getTmpWorkSpace() {
        return tmpWorkSpace;
    }

    public void setTmpWorkSpace(String tmpWorkSpace) {
        this.tmpWorkSpace = tmpWorkSpace;
    }

    public String getPackagePrefix() {
        return packagePrefix;
    }

    public void setPackagePrefix(String packagePrefix) {
        this.packagePrefix = packagePrefix;
    }

    public void init() {
        cidevClient = new CidevClient();
        cidevClient.setAccessKey(this.accessKey);
        cidevClient.setAccessKeySn(this.accessKeySn);
        cidevClient.setApiUrlPre(this.apiUrlPre);

    }

    protected boolean uploadZipAndDes(
            GetUploadTokenResponseBody uploadTokenBody, String type,
            String accessKeySn) throws Exception {

        String key = uploadTokenBody.getKey();
        String uploadToken = uploadTokenBody.getUploadToken();
        String desKey = accessKeySn + key;
        String zipPath = this.tmpWorkSpace + File.separator + key + ".zip";
        String desFilePath = this.tmpWorkSpace + File.separator + key + type
                + ".des";
        // 压缩
        ZipFileHelper.zip(this.srcFile, zipPath);
        FileInputStream zipFileIs = new FileInputStream(zipPath);
        FileOutputStream encFileFo = new FileOutputStream(desFilePath);
        // 加密
        EncryptHelper.encrypt(desKey, zipFileIs, encFileFo);

        cidevClient.upload(desFilePath, key, uploadToken);
        // 删除中间文件.des和.zip
        new File(desFilePath).delete();
        new File(zipPath).delete();
        return true;

    }

    protected boolean downloadEncAndUnzip(String downloadUrl, String desKey)
            throws Exception {
        String desModule = this.tmpWorkSpace + File.separator + this.moduleName
                + ".des";
        String zipPath = this.tmpWorkSpace + File.separator + this.moduleName
                + ".zip";
        int byteread = 0;
        URLConnection conn = new URL(downloadUrl).openConnection();
        InputStream inStream = conn.getInputStream();

        FileOutputStream fs = new FileOutputStream(desModule);
        byte[] buffer = new byte[4096];
        while ((byteread = inStream.read(buffer)) != -1) {
            fs.write(buffer, 0, byteread);
        }
        fs.close();
        inStream.close();
        FileInputStream decFileFs = new FileInputStream(desModule);
        FileOutputStream srcFileFo = new FileOutputStream(zipPath);
        // 解密
        EncryptHelper.decrypt(desKey, decFileFs, srcFileFo);
        String baseSrcDir = this.projectDir + File.separator + this.codeDir
                + File.separator + "src";
        IOHelper.deleteDir(baseSrcDir + "/main/java");
        IOHelper.deleteDir(baseSrcDir + "/test/java");
        // 解压
        ZipFileHelper.unZipFileInToDirectory(zipPath, this.projectDir);
        // 删除Base中间文件.des和.zip
        new File(desModule).delete();
        new File(zipPath).delete();
        return true;

    }

    public boolean generate() throws Exception {
        long beginTime = System.currentTimeMillis();
        String type = "xml";
        if (this.moduleName.equals("Base")) {
            type = "pdm";
        }
        GetUploadTokenRequestBody requestBody = new GetUploadTokenRequestBody();
        requestBody.setFileType(type);
        GetUploadTokenResponseBody uploadTokenBody = cidevClient
                .getUploadToken(requestBody, cidevClient.getAccessKey());

        this.uploadZipAndDes(uploadTokenBody, type,
                cidevClient.getAccessKeySn());
        GetModuleRequestBody getModuleRequestBody = new GetModuleRequestBody();
        getModuleRequestBody.setKey(uploadTokenBody.getKey());
        getModuleRequestBody.setPackagePrefix(this.packagePrefix);
        if(this.appName!=null){
            getModuleRequestBody.setAppName(this.appName);
        }
        GetModuleResponseBody getModuleResponseBody = new GetModuleResponseBody();
        switch (this.moduleName) {
        case "Base":
            getModuleResponseBody = cidevClient.getBaseModule(
                    getModuleRequestBody, cidevClient.getAccessKey());
            break;
        case "Bundle":
            getModuleResponseBody = cidevClient.getBundleModule(
                    getModuleRequestBody, cidevClient.getAccessKey());
            break;
        case "BundleMock":
            getModuleResponseBody = cidevClient.getBundleMockModule(
                    getModuleRequestBody, cidevClient.getAccessKey());
            break;
        case "SDK":
            getModuleResponseBody = cidevClient.getSDKModule(
                    getModuleRequestBody, cidevClient.getAccessKey());
            break;
        case "Client":
            getModuleResponseBody = cidevClient.getSimpleModule(
                    getModuleRequestBody, cidevClient.getAccessKey());
            break;
        case "SimpleClient":
            getModuleResponseBody = cidevClient.getSimpleModule(
                    getModuleRequestBody, cidevClient.getAccessKey());
            break;
        default:
            throw new Exception(this.moduleName + "参数错误");

        }

        String downloadUrl = getModuleResponseBody.getDownloadPath();
        String bundleDesKey = this.cidevClient.getAccessKeySn()
                + getModuleResponseBody.getDesKey();
        this.downloadEncAndUnzip(downloadUrl, bundleDesKey);
        long endTime = System.currentTimeMillis();
        log.info(moduleName + " generation end with duration:"
                + (endTime - beginTime) + "ms");
        return true;
    }

    public String getProjectDir() {
        return projectDir;
    }

    public void setProjectDir(String projectDir) {
        this.projectDir = projectDir;
    }

}
